#include "stdlib.h"
#include "stdio.h"
#include <gtest/gtest.h>

#include <string>

extern "C" {
#include "rtdev/tio_gripper.h"
#include "rtdev/rs485cmdque.h"
}

/************************************************************************************************************************
 *  测试 tio_sensor
 * **********************************************************************************************************************/
static uint8_t MyCRC_GetCRC8(uint8_t* pDat, uint8_t bytes)
{
    uint8_t CRC8_POLY = 0x8C;  // X^8 + X^5 + X^4 + 1
    uint8_t crc;
    uint8_t temp = 0x00, nLen = 0x00;
    uint8_t i = 0x00;
    crc = 0x00;
    nLen = bytes;
    //crc check
    while (nLen--)
    {
        crc = crc ^ *pDat;
        for (i = 0x00; i < 8; i++)
        {
            temp = (crc & 0x01);
            crc >>= 1;
            if (temp)
                crc ^= CRC8_POLY;
        }
        pDat++;
    }
    return crc;
}

class TIOTestSensor : public ::testing::Test
{
protected:
    // void SetUp() override { InitRs485Msg(); }
};

TEST_F(TIOTestSensor, GRIPPER_ADD_DEL)
{
    unsigned char data[12] = {0xaa, 0x55, 0x06, 0x32, 0x09, 0xa8, 0x19, 0x60, 0x50, 0x1a, 0x00, 0xd7};
    unsigned char crc = MyCRC_GetCRC8(data + 2, 9);
    EXPECT_EQ(data[11], crc);
}

/************************************************************************************************************************
 *  测试 tio_gripper
 * **********************************************************************************************************************/
class TIOTestGripper : public ::testing::Test
{
protected:
    // void SetUp() override { InitRs485Msg(); }
};

TEST_F(TIOTestGripper, GRIPPER_ADD_DEL)
{
    // 测试信号添加
    EXPECT_EQ(tio_gripper_has_signal(), 0);
    EXPECT_EQ(tio_gripper_add_signal("abcd", 0, 0x01, 0x01, 0x1234), 0);
    EXPECT_EQ(tio_gripper_has_signal(), 1);
    GripperStateUnit* gripper = checkGripperSigByName("abcd");
    ASSERT_TRUE(gripper != NULL);
    EXPECT_EQ(gripper->commu_state, 0);
    EXPECT_EQ(gripper->freq, 0);
    EXPECT_EQ(gripper->value, 0);
    EXPECT_EQ(gripper->addr, 0x1234);

    // 重复信号的添加
    EXPECT_EQ(tio_gripper_add_signal("abcd", 0, 0x12, 0x34, 0x124), 0);

    EXPECT_EQ(tio_gripper_add_signal("ab_cd", 0, 0x01, 0x01, 0x234), 0);
    EXPECT_EQ(tio_gripper_has_signal(), 2);
    gripper = checkGripperSigByName("abcd");
    ASSERT_TRUE(gripper != NULL);
    EXPECT_EQ(gripper->commu_state, 0);
    EXPECT_EQ(gripper->freq, 0);
    EXPECT_EQ(gripper->value, 0);
    EXPECT_EQ(gripper->addr, 0x124);

    EXPECT_EQ(tio_gripper_add_signal("abcd", 0, 0x01, 0x01, 0x1234), 0);

    // 信号删除
    EXPECT_EQ(tio_gripper_del_signal("abcd"), 0);
    EXPECT_EQ(tio_gripper_del_signal("abcd"), -1);
    EXPECT_EQ(tio_gripper_has_signal(), 1);
    gripper = checkGripperSigByName("abcd");
    ASSERT_TRUE(gripper == NULL);
    gripper = checkGripperSigByName("ab_cd");
    ASSERT_TRUE(gripper != NULL);
    EXPECT_EQ(gripper->commu_state, 0);
    EXPECT_EQ(gripper->freq, 0);
    EXPECT_EQ(gripper->value, 0);
    EXPECT_EQ(gripper->addr, 0x234);
}

// 测试信号量
TEST_F(TIOTestGripper, GRIPPER_CMD)
{
    // 清除信号列表
    tio_gripper_clr_signal(0);
    tio_gripper_clr_signal(1);
    EXPECT_EQ(tio_gripper_has_signal(), 0);

    for (int i = 0; i < MAX_TIO_SIG_NUM; i++)
    {
        std::string sig_name = "abcd_" + std::to_string(i);
        EXPECT_EQ(tio_gripper_add_signal(sig_name.c_str(), i % 2, i, i, 0x1234 + i), 0);
        EXPECT_EQ(tio_gripper_has_signal(), i + 1);
        GripperStateUnit* gripper = checkGripperSigByName(sig_name.c_str());
        ASSERT_TRUE(gripper != NULL);
        EXPECT_EQ(gripper->commu_state, 0);
        EXPECT_EQ(gripper->freq, 0);
        EXPECT_EQ(gripper->value, 0);
        EXPECT_EQ(gripper->addr, 0x1234 + i);
    }
    EXPECT_EQ(tio_gripper_add_signal("abcd", 1, 1, 1, 0x1234 + 1), -1);
    GripperStateUnit* gripper = checkGripperSigByName("abcd");
    ASSERT_TRUE(gripper == NULL);

    // 清除某个通道
    tio_gripper_clr_signal(0);
    EXPECT_EQ(tio_gripper_has_signal(), 4);
    for (int i = 1; i < MAX_TIO_SIG_NUM; i = i + 2)  // 保留信号
    {
        std::string sig_name = "abcd_" + std::to_string(i);
        GripperStateUnit* gripper = checkGripperSigByName(sig_name.c_str());
        ASSERT_TRUE(gripper != NULL);
        EXPECT_EQ(gripper->commu_state, 0);
        EXPECT_EQ(gripper->freq, 0);
        EXPECT_EQ(gripper->value, 0);
        EXPECT_EQ(gripper->addr, 0x1234 + i);
        EXPECT_EQ(gripper->chnId, 1);
    }
    for (int i = 0; i < MAX_TIO_SIG_NUM; i = i + 2)  // 已删除信号
    {
        std::string sig_name = "abcd_" + std::to_string(i);
        GripperStateUnit* gripper = checkGripperSigByName(sig_name.c_str());
        ASSERT_TRUE(gripper == NULL);
    }

    // 测试指令的更新
    int chn_mode[2] = {0, 0};
    EXPECT_EQ(tio_gripper_update_signal("abcd_1", 10, chn_mode), 0);
    EXPECT_EQ(tio_gripper_update_signal("abcd", 10, chn_mode), -1);
    gripper = checkGripperSigByName("abcd_1");
    ASSERT_TRUE(gripper != NULL);
    EXPECT_EQ(gripper->commu_state, GRIPPER_WAITING_REC_NORMAL);  // 发送中
    EXPECT_EQ(gripper->freq, 10);
    EXPECT_EQ(gripper->value, 0);

    // 检查Update后的指令
    EXPECT_FALSE(RsCmdQueIsEmpty());
    RSRTUCMD* cmd = RsCmdQuePeek();
    ASSERT_TRUE(cmd != NULL);
    EXPECT_STREQ(cmd->sigName, "abcd_1");
    EXPECT_EQ(cmd->type, RTU_TYPE);

    // 测试信号指令的自动添加
    int chn_enbale[2] = {1, 0};
    int time_count = 1;
    while (time_count++)
    {
        if (time_count > 2)
        {
            break;
        }
        checkSignalUpdate(chn_enbale, chn_mode);
        EXPECT_EQ(RsCmdQueSize(), 1);
        for (int i = 1; i < MAX_TIO_SIG_NUM; i = i + 2)
        {
            std::string sig_name = "abcd_" + std::to_string(i);
            GripperStateUnit* gripper = checkGripperSigByName(sig_name.c_str());
            ASSERT_TRUE(gripper != NULL);
            if (i == 1)
                EXPECT_EQ(gripper->commu_state, GRIPPER_WAITING_REC_NORMAL);
            else
                EXPECT_EQ(gripper->freq, 0);
            if (i == 1)
                EXPECT_EQ(gripper->freq, 10);
            else
                EXPECT_EQ(gripper->freq, 0);
            EXPECT_EQ(gripper->value, 0);
            EXPECT_EQ(gripper->addr, 0x1234 + i);
        }
    }

    chn_enbale[1] = 1;
    time_count = 1;
    while (time_count++)
    {
        if (time_count > 2)
        {
            break;
        }
        checkSignalUpdate(chn_enbale, chn_mode);
        EXPECT_EQ(RsCmdQueSize(), 4);
        for (int i = 1; i < MAX_TIO_SIG_NUM; i = i + 2)
        {
            std::string sig_name = "abcd_" + std::to_string(i);
            GripperStateUnit* gripper = checkGripperSigByName(sig_name.c_str());
            ASSERT_TRUE(gripper != NULL);
            EXPECT_EQ(gripper->commu_state, GRIPPER_WAITING_REC_NORMAL);
        }
    }

    EXPECT_EQ(tio_gripper_update_signal("abcd_1", 10, chn_mode), 0);
    EXPECT_EQ(gripper->count, 2);  // 发送中
    EXPECT_EQ(tio_gripper_update_signal("abcd_1", 10, chn_mode), 0);
    EXPECT_EQ(gripper->count, 3);  // 发送中

    RsCmdQueReset();
    tio_gripper_reset_send_state();
    for (int i = 1; i < MAX_TIO_SIG_NUM; i = i + 2)
    {
        std::string sig_name = "abcd_" + std::to_string(i);
        GripperStateUnit* gripper = checkGripperSigByName(sig_name.c_str());
        ASSERT_TRUE(gripper != NULL);
        EXPECT_EQ(gripper->commu_state, GRIPPER_WAITING_TO_SEND_NORMAL);
        EXPECT_EQ(gripper->count, 0);
    }
}

/************************************************************************************************************************
 *  测试 R485Msg 循环队列
 * **********************************************************************************************************************/
class TIOTestRS485Mesg : public ::testing::Test
{
protected:
    // void SetUp() override { InitRs485Msg(); }
};

// 测试指令队列
TEST_F(TIOTestRS485Mesg, RS485_MSG_ALOT)
{
    for (int chn = 0; chn < 2; chn++)
    {
        unsigned char msg_num[100] = {};
        for (int i = 0; i < 100; i++) { msg_num[i] = i; }

        unsigned char msg_abc[100] = {};
        for (char i = 'A'; i < 'z'; i++) { msg_abc[i - 'A'] = i; }

        // 初始进入，指令队列为空；
        // InitRs485Msg();

        // // 测试大量压栈
        // EXPECT_EQ(RsMsgEnqueueAlot(chn, msg_num, 100), 100);
        // EXPECT_FALSE(RsMsgQueIsEmpty(chn));
        // EXPECT_TRUE(RsMsgQueIsFull(chn));
        // EXPECT_EQ(RsMsgQueSize(chn), 100);

        // unsigned char data[MAX_MSG_LEN] = {};
        // // 测试部分出栈
        // EXPECT_EQ(RsMsgDequeueAlot(chn, data, 10), 10);
        // EXPECT_FALSE(RsMsgQueIsEmpty(chn));
        // EXPECT_FALSE(RsMsgQueIsFull(chn));
        // EXPECT_EQ(RsMsgQueSize(chn), 100 - 10);
        // for (int i = 0; i < 10; i++) { data[i] = i; }

        // EXPECT_EQ(RsMsgDequeueAlot(chn, data, 34), 34);
        // EXPECT_FALSE(RsMsgQueIsEmpty(chn));
        // EXPECT_FALSE(RsMsgQueIsFull(chn));
        // EXPECT_EQ(RsMsgQueSize(chn), 100 - 10 - 34);
        // for (int i = 10; i < 10 + 34; i++) { data[i - 10] = i; }

        // // 测试全部出栈
        // EXPECT_EQ(RsMsgQueGetAll(chn, data), 100 - 10 - 34);
        // EXPECT_TRUE(RsMsgQueIsEmpty(chn));
        // EXPECT_EQ(RsMsgQueSize(chn), 0);
        // for (int i = 10 + 34; i < 100; i++) { data[i - 10 - 34] = i; }

        // // 测试部分入栈
        // EXPECT_EQ(RsMsgEnqueueAlot(chn, msg_abc, 10), 10);
        // EXPECT_FALSE(RsMsgQueIsEmpty(chn));
        // EXPECT_FALSE(RsMsgQueIsFull(chn));
        // EXPECT_EQ(RsMsgQueSize(chn), 10);

        // EXPECT_EQ(RsMsgEnqueueAlot(chn, msg_abc, 10), 20);
        // EXPECT_FALSE(RsMsgQueIsEmpty(chn));
        // EXPECT_FALSE(RsMsgQueIsFull(chn));
        // EXPECT_EQ(RsMsgQueSize(chn), 20);

        // // 测试入栈替换
        // EXPECT_EQ(RsMsgEnqueueAlot(chn, msg_num, 100), 100);
        // EXPECT_FALSE(RsMsgQueIsEmpty(chn));
        // EXPECT_TRUE(RsMsgQueIsFull(chn));
        // EXPECT_EQ(RsMsgQueSize(chn), 100);

        // EXPECT_EQ(RsMsgEnqueueAlot(chn, msg_abc, 10), 100);
        // EXPECT_FALSE(RsMsgQueIsEmpty(chn));
        // EXPECT_TRUE(RsMsgQueIsFull(chn));
        // EXPECT_EQ(RsMsgQueSize(chn), 100);

        // EXPECT_EQ(RsMsgEnqueueAlot(chn, msg_abc, 10), 100);
        // EXPECT_FALSE(RsMsgQueIsEmpty(chn));
        // EXPECT_TRUE(RsMsgQueIsFull(chn));
        // EXPECT_EQ(RsMsgQueSize(chn), 100);

        // // 全部出栈
        // EXPECT_EQ(RsMsgQueGetAll(chn, data), 100);
        // EXPECT_TRUE(RsMsgQueIsEmpty(chn));
        // EXPECT_EQ(RsMsgQueSize(chn), 0);
        // for (int i = 0; i < 80; i++) { data[i] = i + 20; }
        // for (int i = 80; i < 100; i++) { data[i] = 'a' + i - 80; }
    }
}

// 测试指令队列
TEST_F(TIOTestRS485Mesg, RS485_MSG)
{
    unsigned char msg1[100] = {};
    for (int i = 0; i < 100; i++) { msg1[i] = i; }
    unsigned char msg2[100] = {};
    for (int i = 0; i < 100; i++) { msg2[i] = i * 2; }
    // 初始进入，指令队列为空；
    // InitRs485Msg();
    // EXPECT_TRUE(RsMsgQueIsEmpty(0));
    // EXPECT_TRUE(RsMsgQueIsEmpty(1));
    // EXPECT_EQ(RsMsgQueSize(0), 0);
    // EXPECT_EQ(RsMsgQueSize(1), 0);

    // // 测试压栈
    // for (int i = 0; i < 100; i++)
    // {
    //     // 通道1
    //     EXPECT_EQ(RsMsgEnqueue(0, msg1[i]), 0);
    //     EXPECT_FALSE(RsMsgQueIsEmpty(0));
    //     EXPECT_EQ(RsMsgQueSize(0), i + 1);
    //     if (i < 99)
    //         EXPECT_FALSE(RsMsgQueIsFull(0));

    //     // 通道2
    //     EXPECT_EQ(RsMsgEnqueue(1, msg2[i]), 0);
    //     EXPECT_FALSE(RsMsgQueIsEmpty(1));
    //     EXPECT_EQ(RsMsgQueSize(1), i + 1);
    //     if (i < 99)
    //         EXPECT_FALSE(RsMsgQueIsFull(1));
    // }

    // // 满栈后压栈
    // // 通道1
    // EXPECT_EQ(RsMsgEnqueue(0, 'X'), 0);
    // EXPECT_EQ(RsMsgQueSize(0), MAX_MSG_LEN);
    // EXPECT_TRUE(RsMsgQueIsFull(0));
    // // 通道2
    // EXPECT_EQ(RsMsgEnqueue(1, 'X'), 0);
    // EXPECT_EQ(RsMsgQueSize(1), MAX_MSG_LEN);
    // EXPECT_TRUE(RsMsgQueIsFull(1));

    // // 测试出栈
    // unsigned char cmd;
    // for (int i = 0; i < 100; i++)
    // {
    //     // 通道1
    //     EXPECT_EQ(RsMsgDequeue(0, &cmd), 0);
    //     if (i < 99)
    //         ASSERT_EQ(cmd, i + 1);
    //     else
    //         ASSERT_EQ(cmd, 'X');
    //     if (i < 99)
    //         EXPECT_FALSE(RsMsgQueIsEmpty(0));
    //     EXPECT_EQ(RsMsgQueSize(0), MAX_MSG_LEN - i - 1);
    //     EXPECT_FALSE(RsMsgQueIsFull(0));

    //     // 通道2
    //     EXPECT_EQ(RsMsgDequeue(1, &cmd), 0);
    //     if (i < 99)
    //         ASSERT_EQ(cmd, (i + 1) * 2);
    //     else
    //         ASSERT_EQ(cmd, 'X');
    //     if (i < 99)
    //         EXPECT_FALSE(RsMsgQueIsEmpty(1));
    //     EXPECT_EQ(RsMsgQueSize(1), MAX_MSG_LEN - i - 1);
    //     EXPECT_FALSE(RsMsgQueIsFull(1));
    // }
    // // 空栈后出栈
    // EXPECT_EQ(RsMsgDequeue(0, &cmd), -1);
    // EXPECT_EQ(RsMsgDequeue(1, &cmd), -1);
}

/************************************************************************************************************************
 *  测试 R485Cmd 循环队列
 * **********************************************************************************************************************/
class TIOTestRS485Cmd : public ::testing::Test
{
protected:
    void SetUp() override { RsCmdQueReset(); }
    static RSRTUCMD rs485_rtu_cmd[5];
    static RSRTUCMD rs485_inst_cmd[5];
};

RSRTUCMD TIOTestRS485Cmd::rs485_rtu_cmd[5] = {{RTU_TYPE, WAITING_SEND, "rs485_rtu_cmd_1"},
                                              {RTU_TYPE, WAITING_SEND, "rs485_rtu_cmd_2"},
                                              {RTU_TYPE, WAITING_SEND, "rs485_rtu_cmd_3"},
                                              {RTU_TYPE, WAITING_SEND, "rs485_rtu_cmd_4"},
                                              {RTU_TYPE, WAITING_SEND, "rs485_rtu_cmd_5"}};

RSRTUCMD TIOTestRS485Cmd::rs485_inst_cmd[5] = {{INST_TYPE, WAITING_SEND, "rs485_inst_cmd_1"},
                                               {INST_TYPE, WAITING_SEND, "rs485_inst_cmd_2"},
                                               {INST_TYPE, WAITING_SEND, "rs485_inst_cmd_3"},
                                               {INST_TYPE, WAITING_SEND, "rs485_inst_cmd_4"},
                                               {INST_TYPE, WAITING_SEND, "rs485_inst_cmd_5"}};

// 测试指令队列
TEST_F(TIOTestRS485Cmd, RS485_CMD)
{
    // 初始进入，指令队列为空；
    EXPECT_TRUE(RsCmdQueIsEmpty());
    EXPECT_EQ(RsCmdQueSize(), 0);

    // 测试压栈
    for (int i = 0; i < 5; i++)
    {
        EXPECT_EQ(RsCmdEnqueue(rs485_rtu_cmd[i]), 0);
        EXPECT_FALSE(RsCmdQueIsEmpty());
        EXPECT_EQ(RsCmdQueSize(), i + 1);
        EXPECT_FALSE(RsCmdQueIsFull());
    }
    for (int i = 0; i < 2; i++)
    {
        EXPECT_EQ(RsCmdEnqueue(rs485_inst_cmd[i]), 0);
        EXPECT_FALSE(RsCmdQueIsEmpty());
        EXPECT_EQ(RsCmdQueSize(), i + 1 + 5);
        EXPECT_FALSE(RsCmdQueIsFull());
    }
    EXPECT_EQ(RsCmdEnqueue(rs485_inst_cmd[2]), 0);
    EXPECT_EQ(RsCmdQueSize(), MAX_QUE_LEN);
    EXPECT_TRUE(RsCmdQueIsFull());

    // 满栈后压栈
    EXPECT_EQ(RsCmdEnqueue(rs485_inst_cmd[2]), -1);
    EXPECT_EQ(RsCmdQueSize(), MAX_QUE_LEN);
    EXPECT_TRUE(RsCmdQueIsFull());

    // 测试出栈
    for (int i = 0; i < 5; i++)
    {
        RSRTUCMD* cmd_ptr = RsCmdQuePeek();
        ASSERT_STREQ(cmd_ptr->sigName, rs485_rtu_cmd[i].sigName);

        RSRTUCMD cmd;
        EXPECT_EQ(RsCmdDequeue(&cmd), 0);
        ASSERT_STREQ(cmd.sigName, rs485_rtu_cmd[i].sigName);
        ASSERT_EQ((int)cmd.type, (int)RTU_TYPE);
        EXPECT_FALSE(RsCmdQueIsEmpty());
        EXPECT_EQ(RsCmdQueSize(), 8 - i - 1);
        EXPECT_FALSE(RsCmdQueIsFull());
    }

    // 测试进出栈
    for (int i = 0; i < 3; i++)
    {
        RSRTUCMD cmd;
        EXPECT_EQ(RsCmdDequeue(&cmd), 0);
        ASSERT_STREQ(cmd.sigName, rs485_inst_cmd[i].sigName);
        ASSERT_EQ((int)cmd.type, (int)INST_TYPE);
        EXPECT_EQ(RsCmdEnqueue(rs485_rtu_cmd[4]), 0);
    }

    EXPECT_FALSE(RsCmdQueIsEmpty());
    EXPECT_EQ(RsCmdQueSize(), 3);
    EXPECT_FALSE(RsCmdQueIsFull());

    // 测试清空
    RsCmdQueReset();
    EXPECT_TRUE(RsCmdQueIsEmpty());
    EXPECT_FALSE(RsCmdQueIsFull());
    RSRTUCMD cmd;
    EXPECT_EQ(RsCmdDequeue(&cmd), -1);
    EXPECT_TRUE(RsCmdQueIsEmpty());
    EXPECT_FALSE(RsCmdQueIsFull());
}

int main(int argc, char* argv[])
{
    printf("Running main() from %s\n", __FILE__);
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}